﻿using System.Globalization;
using System.Collections;
using System.IO;
using System.Text.RegularExpressions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Marbles.Core.Web.Resources;

namespace Marbles.Core.Web.Wiki
{
    public class WikiEngine
    {

        public string SiteName
        {
            get { return this._Sitename; }
            set { this._Sitename = value; }
        }

        private string _Sitename = string.Empty;

        public WikiEngine(string SiteName)
        {
            this._Sitename = SiteName;
        }

        public WikiEngine()
        {
            this._Sitename = string.Empty;
        }

        public string Parse(WikiDocument Document)
        {
            string newvalue = Document.Markup.Trim();
            WikiEngineResource res = new WikiEngineResource();
            StringReader srMatch = new StringReader(res.MatchExpression);
            StringReader srReplace = new StringReader(res.ReplaceExpression);
            string sMatch = string.Empty;
            string sReplace = string.Empty;
            Dictionary<string, string> nowiki = new Dictionary<string, string>();
            newvalue = AddWikiVariables(newvalue, Document.Title, Document.NameSpace, this._Sitename, Document.RevisionId);
            nowiki = GetNoWikiValues(ref newvalue);

            while (true)
            {
                sMatch = srMatch.ReadLine();
                sReplace = srReplace.ReadLine();
                if (sMatch == null) { break; }

                sReplace = AddSystemVariables(sReplace);

                newvalue = Regex.Replace(newvalue, sMatch, sReplace, RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
            }

            newvalue = RestoreNoWikiValues(newvalue, nowiki);

            return newvalue.Trim();
        }

        private string RestoreNoWikiValues(string value, Dictionary<string, string> items)
        {
            string newvalue = value;

            foreach (string s in items.Keys)
            {
                if (s.Substring(0, 5) == "<pre>")
                {
                    newvalue = newvalue.Replace(s, string.Format("<pre>{0}</pre>",items[s]));
                }
                else
                {
                    newvalue = newvalue.Replace(s, items[s]);
                }
            }
            return newvalue.Trim();
        }
        private Dictionary<string, string> GetNoWikiValues(ref string value)
        {
            Dictionary<string, string> items = new Dictionary<string, string>();
            MatchCollection nowiki = Regex.Matches(value, "(?#nowiki)<nowiki>(?<value>.*?)</nowiki>", RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
            MatchCollection pre = Regex.Matches(value, "(?#nowiki)<pre>(?<value>.*?)</pre>", RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
            int index = 0;

            for (int i = 0; i < nowiki.Count; i++)
            {
                index += 1;
                items.Add(string.Format("<nowiki>{0}</nowiki>", index), nowiki[i].Groups["value"].Value);
                value = value.Replace(nowiki[i].ToString(), string.Format("<nowiki>{0}</nowiki>", index));
                // value = Regex.Replace(value, nowiki[i].Groups["value"].Value, index.ToString(), RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
            }

            for (int i = 0; i < pre.Count; i++)
            {
                index += 1;
                items.Add(string.Format("<pre>{0}</pre>", index), pre[i].Groups["value"].Value);
                value = value.Replace(pre[i].ToString(), string.Format("<pre>{0}</pre>", index));
                //value = Regex.Replace(value, pre[i].Groups["value"].Value, index.ToString(), RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);
            }

            return items;
        }

        private string AddSystemVariables(string value)
        {
            string sReplace = value;
            sReplace = sReplace.Replace("[username]", HttpContext.Current.User.Identity.Name);
            sReplace = sReplace.Replace("[datetime]", GetUTCDateTime());
            sReplace = sReplace.Replace("[localurl]", HttpContext.Current.Request.Url.AbsolutePath);
            sReplace = sReplace.Replace("[fullurl]", HttpContext.Current.Request.Url.AbsoluteUri);
            return sReplace;
        }

        private string GetUTCDateTime()
        {
            return DateTime.Now.ToUniversalTime().ToString("ddd, dd MMM yyyy HH':'mm':'ss (UTC)");
        }

        private string AddWikiVariables(string value, string title, string wikinamespace, string sitename, long revisionid)
        {
            string sReplace = value;
            sReplace = sReplace.Replace("{{CURRENTWEEK}}", Marbles.Core.Helpers.DateTools.GetWeekNumberFromDate(DateTime.Now).ToString());
            sReplace = sReplace.Replace("{{CURRENTDOW}}", Convert.ToInt32(DateTime.Now.DayOfWeek).ToString());
            sReplace = sReplace.Replace("{{CURRENTMONTH}}", DateTime.Now.Month.ToString());
            sReplace = sReplace.Replace("{{CURRENTMONTHNAME}}", DateTime.Now.ToString("MMMM"));
            sReplace = sReplace.Replace("{{CURRENTMONTHNAMEGEN}}", DateTime.Now.ToString("MMM"));
            sReplace = sReplace.Replace("{{CURRENTDAY}}", DateTime.Now.Day.ToString());
            sReplace = sReplace.Replace("{{CURRENTDAYNAME}}", DateTime.Now.DayOfWeek.ToString());
            sReplace = sReplace.Replace("{{CURRENTYEAR}}", DateTime.Now.Year.ToString());
            sReplace = sReplace.Replace("{{CURRENTFISCALYEAR}}", Marbles.Core.Helpers.DateTools.FiscalYearFromDate(DateTime.Now).ToString());            
            sReplace = sReplace.Replace("{{CURRENTFISCALQUARTER}}", Marbles.Core.Helpers.DateTools.FiscalQuarterFromDate(DateTime.Now).ToString());
            sReplace = sReplace.Replace("{{CURRENTFISCALPERIOD}}", Marbles.Core.Helpers.DateTools.FiscalPeriodFromDate(DateTime.Now).ToString());
            sReplace = sReplace.Replace("{{CURRENTTIME}}", DateTime.Now.ToString("HH:mm:ss"));
            sReplace = sReplace.Replace("{{CURRENTCULTURE}}", CultureInfo.CurrentCulture.Name);
            sReplace = sReplace.Replace("{{CLIENTLANGUAGE}}", Marbles.Core.Helpers.WebBrowser.GetLanguages());
            sReplace = sReplace.Replace("{{CLIENTADDRESS}}", HttpContext.Current.Request.UserHostAddress);
            sReplace = sReplace.Replace("{{CURRENTLANGUAGE}}", CultureInfo.CurrentCulture.TwoLetterISOLanguageName);            
            sReplace = sReplace.Replace("{{NUMBEROFARTICLES}}", "0");
            sReplace = sReplace.Replace("{{NUMBEROFUSERS}}", "0");
            sReplace = sReplace.Replace("{{PAGENAME}}", title);
            sReplace = sReplace.Replace("{{NAMESPACE}}", wikinamespace);
            sReplace = sReplace.Replace("{{REVISIONID}}", revisionid.ToString());
            sReplace = sReplace.Replace("{{fullurl:pagename}}", HttpContext.Current.Request.Url.AbsoluteUri);
            sReplace = sReplace.Replace("{{localurl:pagename}}", HttpContext.Current.Request.Url.AbsolutePath);
            sReplace = sReplace.Replace("{{SERVER}}", HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Scheme) + HttpContext.Current.Request.Url.Host);
            sReplace = sReplace.Replace("{{SITENAME}}", sitename);
            sReplace = sReplace.Replace("{{SOFTWARE}}", Marbles.Core.Helpers.System.GetVersion());
            sReplace = sReplace.Replace("{{SOFTWAREVERSION}}", Marbles.Core.Helpers.System.GetFullVersion());
            sReplace = sReplace.Replace("{{PLATFORM}}", Marbles.Core.Helpers.System.GetPlatform());
            sReplace = sReplace.Replace("{{CLIENTNAME}}", Marbles.Core.Helpers.WebBrowser.GetBrowserName());
            sReplace = sReplace.Replace("{{CLIENTVERSION}}", Marbles.Core.Helpers.WebBrowser.GetBrowserVersion());
            sReplace = sReplace.Replace("{{CLIENTDOMVERSION}}", HttpContext.Current.Request.Browser.W3CDomVersion.ToString());
            sReplace = sReplace.Replace("{{CLIENTPLATFORM}}", HttpContext.Current.Request.Browser.Platform);
            sReplace = sReplace.Replace("{{CLIENTSCREENWIDTH}}", HttpContext.Current.Request.Browser.ScreenPixelsWidth.ToString());
            sReplace = sReplace.Replace("{{CLIENTSCREENHEIGHT}}", HttpContext.Current.Request.Browser.ScreenPixelsHeight.ToString());
            return sReplace;

            
        }
    }
}
